package jp.co.systemi.asp.workflow;

import java.util.HashMap;
import java.util.logging.Logger;

import net.arnx.jsonic.JSON;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.FeedbackPanel;

public class Main extends Super {
    private static final long serialVersionUID = 0L;
    private static final Logger log = Logger.getLogger(Main.class.getName());
    /**
     * 二重Submit防止
     */
    public boolean isSubmit = false;
    /** フィードバック */
    protected FeedbackPanel feedback = new FeedbackPanel("wi_feedback");
    protected WebMarkupContainer menu = new WebMarkupContainer("wi_menu");
    public WebMarkupContainer main;
    public static enum MODE{
        NEW,
        EDIT
    };
    protected MODE mode = MODE.NEW;

    public String menuDef =
        "{"
            +"グループ管理:{"
                +"グループ登録:jp.co.systemi.asp.workflow.group.GroupReg,"
                +"グループ検索:jp.co.systemi.asp.workflow.group.GroupSearch"
            +"}"
            +",ユーザ管理:{"
                +"ユーザ登録:jp.co.systemi.asp.workflow.user.UserReg,"
                +"ユーザ検索:jp.co.systemi.asp.workflow.user.UserSearch"
            +"}"
            +",ルート管理:{"
                +"ルート登録:jp.co.systemi.asp.workflow.route.RouteReg"
            +"}"
            +",申請:{"
                +"申請一覧:jp.co.systemi.asp.workflow.apply.ApplyRef"
                +",有給申請登録:jp.co.systemi.asp.workflow.apply.PaidHolidayApply"
                +",有給申請照会:jp.co.systemi.asp.workflow.apply.PaidHolidayRef"
            +"}"
            +",承認:{"
                +"決裁一覧:jp.co.systemi.asp.workflow.approve.ApproveRef"
            +"}"
            +",レポート:{"
                +"有給休暇一覧:jp.co.systemi.asp.workflow.report.PaidHolidayReport"
             +"}"
            +",イベント管理:{"
                +"リマインダー一覧:jp.co.systemi.asp.workflow.mail.ReminderList"
         +"}"
//            +",ユーザ参照:jp.co.systemi.asp.workflow.user.UserRef"
        +"}";
    @SuppressWarnings("unchecked")
    public Main() {
        main = new WebMarkupContainer("wi_mainContentsInner");
        body.add(main);
        main.add(feedback);
        feedback.setOutputMarkupId(true);
        feedback.setEscapeModelStrings(false);

        // Create the menubar
        HashMap<String, Object> menuObj = (HashMap<String, Object>)JSON.decode(menuDef);
        final SuckerfishMenuPanel mb = new SuckerfishMenuPanel("menuBar");
        body.add(mb);
        mb.addMenu(menuObj);
    }
    /**
     * Formの共通処理をまとめる １．二重submit防止 ２．入力項目をFormにaddする処理
     * ３．入力項目のValidatorをAnnotationからadd処理 目的：重要な実装手続きをなるべく共通化し、DRY（Don't Repeat
     * Yourself)を徹底して、 実装漏れを防ぐ、業務仕様に専念できる
     *
     * @author wzhang
     *
     * @param <T>
     */
    public static class MainForm<T> extends Form<T> {
        private static final long serialVersionUID = 8184718708797836858L;
        Main main = null;
        boolean isSubmit = false;

        public MainForm(Main main, String id) {
            super(id);
            this.main = main;

            // フィールドのValidatorをバインディングする
            try{
                main.bindValidators(this);
            }
            catch(Exception e){
                log.info(e.getLocalizedMessage());
                if(e.getCause() != null){
                    for(StackTraceElement msg : e.getCause().getStackTrace()){
                        log.info(msg.getClassName() + ":" + msg.getMethodName() + ":" + msg.getLineNumber());
                    }
                }
                else{
                    log.info("cause is null");
                    for(StackTraceElement msg : e.getStackTrace()){
                        log.info(msg.getClassName() + ":" + msg.getMethodName() + ":" + msg.getLineNumber());
                    }
                }
            }
            log.info("after main.bindValidators");
            // タグの親子関係を維持する
            main.main.add(this);
        }

        @Override
        protected void onSubmit() {
            if (isSubmit) {
                return;
            }
            isSubmit = true;
            try {
                onSubmitInner();
            } finally {
                isSubmit = false;
            }
        };

        /**
         * 継承クラスはこのメソッドを実装し、業務処理だけを記述する 二重submit防止の実装手続きを考える必要がない
         */
        protected void onSubmitInner() {
        }
    };

    /**
     * AjaxButton 二重Submit防止を実装済み
     *
     * @author wzhang
     *
     */
    abstract public static class MainAjaxButton extends AjaxButton {
        private static final long serialVersionUID = 1L;
        private Main main = null;

        public MainAjaxButton(Main main, String id) {
            super(id);
            this.main = main;
        }

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
            if (main.isSubmit) {
                return;
            }
            main.isSubmit = true;

            try {
                onSubmitInner(target, form);
            } finally {
                main.isSubmit = false;
            }

        }

        abstract protected void onSubmitInner(AjaxRequestTarget arg0,
                Form<?> arg1);
    }
}
